package com.darwin.darwinImage.darx
{
	import com.darwin.darwinDisplay.BitmapFilterList;
	import com.darwin.darwinDisplay.DarXBitmapData;
	
	import flash.display.BitmapData;
	import flash.display.Shader;
	import flash.display.Shape;
	import flash.filters.BitmapFilter;
	import flash.filters.GlowFilter;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.getTimer;
	import flash.utils.setTimeout;

	/**
	 *	【工具类】深度贴图动画的合成器，提供合成数个DarXBitmapData动画的静态方法
	 * @author Roland
	 * 
	 */
	public class DarXSynthesizer
	{
		[Embed (source="embed/zMapMix.pbj", mimeType="application/octet-stream")]
		private static var zMapMixShaderCode:Class;

		private static var FILTER_OFFSET:int = 40;
		
		/**
		 *	合成操作在1帧中最多允许占用的时间(ms)，若超过此时间将操作挂起，等到下一帧继续执行 
		 */
		public static var frameLimitTime:int = 10; 
		
		public function DarXSynthesizer()
		{
		}
		
		/**
		 *	合成传入的 darxBitmapData列表为单个动画序列
		 * @param darxBitmapDataList 要合成的列表
		 * @param callBack 合成完毕后的回调函数 function callBack(bitmapDataList:Array,frameOffsetList:Array【可以是Point或Rectangle列表】):void
		 * @param filtersList 要给列表中每部件单独应用的滤镜列表(可选)
		 * @param matrix 要对动画应用的矩阵变换
		 */
		public static function synthesis(darxBitmapDataList:Vector.<DarXBitmapData>,callBack:Function,filtersList:Vector.<BitmapFilterList> = null,matrix:Matrix = null):void
		{
			var $rect:Rectangle = calculateMaxRect(darxBitmapDataList);
			var $frameLength:int = darxBitmapDataList.length > 0 ? darxBitmapDataList[0].frameList.length : 0;
			var $frameList:Array = [];
			var $offsetList:Array = [];
			
			exeSynthesis(0,$frameLength);
			
			function exeSynthesis(from:int,to:int):void
			{
				var $t:int = getTimer();//进入时间
				for (var i:int = from; i < to; i++) 
				{
					var $orgframe:BitmapData = synthesisFrame(darxBitmapDataList,$rect,i,filtersList,matrix);
					var $offsetRect:Rectangle = $orgframe.getColorBoundsRect(0xff000000,0,false);
					var $destPoint:Point = new Point();
					if($offsetRect.width==0)$offsetRect.width = 1;
					if($offsetRect.height==0)$offsetRect.height = 1;
					var $frame:BitmapData = new BitmapData($offsetRect.width,$offsetRect.height,true,0);
					$frame.copyPixels($orgframe,$offsetRect,$destPoint);
					$frameList.push($frame);
					$offsetList.push($offsetRect);
					if(getTimer()-$t > frameLimitTime)//如果循环时间超过frameLimitTime,中断,放到下一帧处理
					{
						setTimeout(exeSynthesis,1,i+1,to);
						return;
					}
				}
				
				if(callBack != null)
				{
					callBack($frameList,$offsetList);
				}
			}

		}
		
		/**
		 * 合成绘制传入darxBitmapdata列表中的指定帧 
		 * @param darxBitmapDataList 要合并的深度贴图动画列表
		 * @param rect 定义绘制的合并后图像区域的矩形。
		 * @param frameIndex 要绘制的帧 (从0开始)
		 * @param filtersList 要对darxBitmapDataList中各部分应用的滤镜列表(可选)
		 * @param matrix 要对动画应用的矩阵变换
		 * @return 
		 * 
		 */
		public static function synthesisFrame(darxBitmapDataList:Vector.<DarXBitmapData>,rect:Rectangle,frameIndex:int,filtersList:Vector.<BitmapFilterList> = null,matrix:Matrix = null):BitmapData
		{
			var $canvas:Shape = new Shape();
			var $shader:Shader = new Shader(new zMapMixShaderCode());
			if(filtersList == null) filtersList = new Vector.<BitmapFilterList>(darxBitmapDataList.length);
			for (var i:int = 0; i < 4; i++) 
			{
				var combineBitmapData:BitmapData = darxBitmapDataList[i] ? getCombineBitmapData(darxBitmapDataList[i],rect,frameIndex,filtersList[i] ? filtersList[i].filtersVec : null) : new BitmapData(1,1,true,0);
				$shader.data["image" + (i + 1) + "Width"].value[0] = rect.width + FILTER_OFFSET;
				$shader.data["equip" + (i + 1)].input = combineBitmapData;
			}

			$canvas.graphics.clear();
			$canvas.graphics.beginShaderFill($shader);
			$canvas.graphics.drawRect(rect.x, rect.y, rect.width,rect.height);
			$canvas.graphics.endFill();
			
			var $bitmapData:BitmapData = new BitmapData(rect.width,rect.height,true,0);
			$bitmapData.draw($canvas,null,null,null,null,true);
			
			if(matrix != null)
			{
				var $transBitmapData:BitmapData = new BitmapData($bitmapData.width,$bitmapData.height,true,0);
				$transBitmapData.draw($bitmapData,matrix,null,null,null,true);
				$bitmapData = $transBitmapData;
			}
			
			return $bitmapData;
		}
		
		private static function calculateMaxRect(darxBitmapDataList:Vector.<DarXBitmapData>):Rectangle
		{
			var _maxRect:Rectangle = new Rectangle();
			for (var i:int = 0; i < darxBitmapDataList.length; i++) 
			{
				var cRect:Rectangle = getRect(darxBitmapDataList[i]);
				_maxRect = _maxRect.union(cRect);
			}
			return _maxRect;
		}
		
		private static function getRect(darx:DarXBitmapData):Rectangle
		{
			if(darx.frameList == null)
			{
				throw new Error("传入的darXBitmapData的位图数据尚未解析");
			}
			var $currentRect:Rectangle = new Rectangle(0,0,0,0);
			for (var i:int = 0; i < darx.frameList.length; i++) 
			{
				var rect:Rectangle = darx.frameList[i].rect;
				var offset:Point = darx.frameOffsetList[i];
				if(offset.x + rect.right > $currentRect.width)
				{
					$currentRect.width = offset.x + rect.right;
				}
				if(offset.y + rect.bottom > $currentRect.height)
				{
					$currentRect.height = offset.y + rect.bottom;
				}
			}
			return $currentRect;
		}
		
		/**
		 *	 获取提供给pb滤镜使用的合成位图数据
		 * @param darx
		 * @param rect
		 * @frameIndex
		 * @filters 要对此部件应用的滤镜组
		 * @return 
		 * 
		 */
		private static function getCombineBitmapData(darx:DarXBitmapData,rect:Rectangle,frameIndex:int,filters:Vector.<BitmapFilter> = null):BitmapData
		{
			var cBitmapData:BitmapData;
			var frame:BitmapData = darx.frameList[frameIndex];
			var zmap:BitmapData = darx.zMapList[frameIndex];
			var offset:Point = darx.frameOffsetList[frameIndex];
			
			//处理滤镜
			var filterFrame:BitmapData;
			var filterZmap:BitmapData;
			
			filterFrame = new BitmapData(frame.width + FILTER_OFFSET,frame.height + FILTER_OFFSET,true,0x000000);
			filterZmap = new BitmapData(zmap.width + FILTER_OFFSET,zmap.height + FILTER_OFFSET,true,0x000000);
			if(filters)
			{
				filterFrame.applyFilter(frame,frame.rect,new Point(FILTER_OFFSET/2,FILTER_OFFSET/2),filters[0]);
				for (var i:int = 1; i < filters.length; i++) 
				{
					filterFrame.applyFilter(filterFrame,filterFrame.rect,new Point(),filters[i]);
				}
				filterZmap.copyPixels(zmap,zmap.rect,new Point(FILTER_OFFSET/2,FILTER_OFFSET/2));
			}else{
				filterFrame.copyPixels(frame,frame.rect,new Point(FILTER_OFFSET/2,FILTER_OFFSET/2));
				filterZmap.copyPixels(zmap,zmap.rect,new Point(FILTER_OFFSET/2,FILTER_OFFSET/2));
			}
			
			//申请位图
			cBitmapData = new BitmapData(rect.width*2 + FILTER_OFFSET*2,rect.height + FILTER_OFFSET*2,true,0x000000);
			cBitmapData.copyPixels(filterZmap,filterZmap.rect,new Point(offset.x - FILTER_OFFSET,offset.y - FILTER_OFFSET));
			cBitmapData.copyPixels(filterFrame,filterFrame.rect,new Point(offset.x - FILTER_OFFSET + rect.width + FILTER_OFFSET,offset.y - FILTER_OFFSET));
			return cBitmapData;
		}
		

	}
}